<?php
namespace Core;

use PDOStatement, Iterator, ArrayAccess, Countable;

/**
 * 数据库查询结果集对象
 * 
 * 此类实现了如下接口：
 * 1、Iterator：可使用 foreach 语句和 each() 函数遍历结果集
 * 2、ArrayAccess：允许以数组方式访问指定偏移量的数据记录
 * 3、Countable：可使用 count() 函数获得结果集中的数据记录总数量
 * 
 */
final class DbResult implements Iterator, ArrayAccess, Countable {
	/**
	 * 结果集中的数据记录总数量
	 * @var int
	 * @access public
	 */
	public $count = 0;
	
	/**
	 * 遍历结果集时，指针的当前偏移量
	 * @var int
	 * @access private
	 */
	private $offset = 0;
	/**
	 * 结果集
	 * @var int
	 * @access private
	 */
	private $result = array();
	
	/**
	 * 初始一个结果集对象
	 * 
	 * @param PDOStatement $statement
	 */
	public function __construct(PDOStatement $statement) {
		$this->result = $statement->fetchAll(\PDO::FETCH_ASSOC);
		$this->count = count($this->result);
	}
	
	/**
	 * 获得结果集中的指定记录，各参数介绍见 array_slice() 函数
	 * 
	 * @param int $start
	 * @param int $length
	 * @return array
	 */
	public function fetch($start = 0, $length = NULL) {
		return array_slice($this->result, $start, $length);
	}
	
	/**
	 * 开始遍历，复位指针
	 * 
	 * @return void
	 */
	public function rewind() {
		$this->offset = 0;
	}
	
	/**
	 * 遍历过程中，获得当前偏移量的键
	 * 
	 * @return int
	 */
	public function key() {
		return $this->offset;
	}
	
	/**
	 * 遍历过程中，获得当前偏移量的值
	 * 
	 * @return array
	 */
	public function current() {
		return $this->result[$this->offset];
	}
	
	/**
	 * 遍历过程中，将指针移至下一条
	 * 
	 * @return void
	 */
	public function next() {
		$this->offset++;
	}
	
	/**
	 * 遍历过程中，每次调用 self::next() 和 self::rewind() 之后，检查指针当前偏移量是否存在数据记录
	 * 
	 * @return boolean
	 */
	public function valid() {
		return $this->offset < $this->count;
	}
	
	/**
	 * 判断指定偏移量是否存在数据记录
	 * 
	 * @param int $offset
	 * @return boolean
	 */
	public function offsetExists($offset) {
		return isset($this->result[$offset]);
	}
	
	/**
	 * 获得指定偏移量的数据记录
	 * 
	 * @param int $offset
	 * @return array
	 */
	public function offsetGet($offset) {
		return isset($this->result[$offset]) ? $this->result[$offset] : NULL;
	}
	
	/**
	 * 接口 ArrayAccess 的实现
	 * 
	 * @param int $offset
	 * @param array $value
	 * @return void
	 */
	public function offsetSet($offset, $value) {
		trigger_error('Can not modify the database result sets', E_USER_WARNING);
	}
	
	/**
	 * 接口 ArrayAccess 的实现
	 * 
	 * @param int $offset
	 * @return void
	 */
	public function offsetUnset($offset) {
		trigger_error('Can not unset a database result sets', E_USER_WARNING);
	}
	
	/**
	 * 获得结果集中的数据记录总数量
	 * 
	 * @return int
	 */
	public function count() {
		return $this->count;
	}
}